# $Id: autotools.sh.in 965 2009-04-27 16:34:04Z enki $
#
# buildsys/autotools.sh: autotools (GNU autoconf, automake, libtool) source package functions
# ---------------------------------------------------------------------------
[ "$lib_buildsys_autotools_sh" ] || {

# ---------------------------------------------------------------------------
: ${prefix:="@prefix@"} # default for prefix
: ${exec_prefix:="@prefix@"}
: ${sysconfdir:="/etc"} # default value for sysconfdir
: ${libdir:="${exec_prefix}/lib"} # default value for libdir
: ${bindir:="${exec_prefix}/bin"} # default value for bindir
: ${shlibdir:="${libdir}/sh"}

# ---------------------------------------------------------------------------
. $shlibdir/std/array.sh
. $shlibdir/shell/emit.sh
. $shlibdir/data/obj.sh

# ---------------------------------------------------------------------------
aclocal_sources="{*,*/*}.{ac,m4}"
autoconf_sources="configure.{in,ac} aclocal.m4"
autoheader_sources="acconfig.h"
automake_sources="Makefile.am"
libtool_sources=""
autotools_sources="$aclocal_sources ${autoconf_sources} $autoheader_sources $automake_sources $libtool_sources"

# ---------------------------------------------------------------------------
aclocal_files="aclocal.m4"
autoconf_files="configure"
autoheader_files="*.h.in"
automake_files="Makefile.in config.{guess,sub}"
libtool_files="ltmain.sh config.guess config.sub"
autotools_files="${aclocal_files} ${autoconf_files} ${autoheader_files} ${automake_files} ${libtool_files}"

# ---------------------------------------------------------------------------
aclocal_generated="autom4te.cache"
autoconf_generated="config.{cache,status,log}"
autoheader_generated="config.h"
automake_generated="Makefile install-sh missing depcomp .deps .libs"
libtool_generated="libtool"
autotools_generated="${aclocal_generated} ${autoconf_generated} ${autoheader_generated} ${automake_generated} ${libtool_generated}"

# ---------------------------------------------------------------------------
_autotools_names()
{
 (IFS=" $newline$tabstop"
  set -f
  eval set -- $*
  for x
  do
    echo -name "$x"
  done)
}

# autotools_test [directory]
# -------------------------------------------------------------------------
autotools_test()
{
  [ -f "${1-.}/configure" ]
}

# autotools_scan [directories...]
#
# searches one or more directory trees for any of $autotools_sources.
# -------------------------------------------------------------------------
autotools_scan()
{
  find "$@" -name configure.in -or -name configure.ac -or -name configure |
  {
    prev=
    while read template; do
      this=`dirname "$template"`
	  if [ "$this" != "$prev" ]; then
	    echo "$this"
	  fi
	  prev="$this"
    done
  }
  #local names=`_autotools_names "${autoconf_sources} $autoconf_files $libtool_files"`
  #
  #(set -f
  # IFS=" "
  # find "${@:-.}" -type f `array_implode names ' -or '` | sed -e "s,/[^/]\+$,," -e "s,^\.\/,," | sort -u)
}

# autotools_args <directory>
#
# Get the arguments of the last ./configure run in the specified directory
# -------------------------------------------------------------------------
autotools_args()
{
  sed -n \
      -e '\|/configure,| {
            /^configured by / { 
              N
              s/\s\+/ /g
              s/^\s*configured by //
              s/, generated by GNU Autoconf.*with options//

              /\\".*\\"$/ {
                s,^.*/configure\s\+\\"\(.*\)\\"$,\1,
              }
            }
            s,"\([^"]\+\)",\1,g

            s,.*/configure\s\+\"\?\s*,,
            s,\s*$ac_configure_extra_args.*,,

            s,%g\$,,
            s,\;;,,

            s,'\''\([^'\'']*\)'\''\s*,\1\n,g
            ##s,\s,\n,g            
            p
            q
          }' \
    ${1+$1/}config.{status,log} 2>/dev/null
}

# autotools_recheck [directories...]
#
# Re-run ./configure.ac each directory.
# -------------------------------------------------------------------------
autotools_recheck()
{
  local dir IFS='
'
  for dir
  do
   (trap 'exit 127' INT HUP TERM QUIT
   
    cd $dir
     
    if test $dir != .
    then
      msg "cd `pwd`"
    fi

    # Check for presence of config.{status,log}
    cfg_cmds="./configure `autotools_args`"

    case $cfg_cmds in
      *"'"* | *'"'*)
        eval "set -- $cfg_cmds && cfg_cmds=$*"
        ;;
    esac

#    echo "Config cmds:" $cfg_cmds

    $cfg_cmds 2>/dev/null

   )
  done
}

# autotools_is_m4 <files...>
#
# -------------------------------------------------------------------------
autotools_is_m4()
{
  local file IFS="
"
  for file
  do
    case $file in
      configure.ac|configure.ac) 
        ;;

      *.m4|*.ac) 
        return 0
        ;;
      *)
        case `file -bi $file 2>/dev/null` in
          *:*text/x-m4 | text/x-m4\;*) 
            return 0 
            ;;
        esac
        ;;
    esac
  done

  return 1
}

# autotools_m4_defuns <files...>
#
# -------------------------------------------------------------------------
autotools_m4_defuns()
{
  sed -n \
      -e 's/.*A[CU]_DEFUN([[\s]*\([^],()]\+\).*/\1/p' \
      -e 's/.*m4_define([[\s]*\([^],()]\+\).*/\1/p' \
    "$@" 2>/dev/null
}

# autotools_m4_macro <name> <files...>
#
# -------------------------------------------------------------------------
autotools_m4_macro()
{
  local name=$1
  shift
  sed -n \
      -e "/$name/ {
            :lp1
            s/\s\+/ /g
            /$name\\s*\$/ { N; b lp1; }
      
            /$name\\s*(/ {
              :lp2
              /$name\\s*(.*)/! { N; b lp2; }
              p
            }
          }" \
    "$@" 2>/dev/null
}

# autotools_m4_underquoted <files...>
#
# -------------------------------------------------------------------------
autotools_m4_underquoted()
{
#      -e 's/.*[_0-9A-Z]\+(\([^[]]\+\),.*/\1/p' \
  sed -n \
      -e '/AC_DEFUN/ {
            s/.*AC_DEFUN(\([^,]*\),.*/\1/
            /^[_0-9A-Za-z]*$/p
          }' \
    "$@" 2>/dev/null
}

# autotools_m4_fixquote <files...>
#
# -------------------------------------------------------------------------
autotools_m4_fixquote()
{
  local files underq def IFS="
"
  files="$*"
  underq=`autotools_m4_underquoted "$@"`

  set --

  for def in $underq; do
    set -- "$@" -e "s/(\([^[(_0-9A-Za-z]*\)${def}\([^],_0-9A-Za-z]*\)/(\1\[${def}\]\2/g"
  done

  sed -i "$@" $files 2>/dev/null
}

# autotools_bootstrap [directory]
#
# -------------------------------------------------------------------------
autotools_bootstrap()
{
 (dir= n=1 aclocal= automake= autoheader= autoconf= libtoolize= topdir= auxdir= prog= IFS=" ""
" redir= save="no"

  . $shlibdir/shell/cmd.sh

  aclocal='aclocal'
  automake='automake'
  autoheader='autoheader'
  autoconf='autoconf'
  libtoolize='libtoolize'

  while [ -n "$1" -a "$1" != "${1#-}" ]; do
    n=1
    case $1 in
      -w | -s | --write | --save)
        save="yes"
        shift
        continue
        ;;
        
      --quiet) 
        redir=">&/dev/null"
        shift
        continue
        ;;
    esac
  
    for prog in libtoolize aclocal automake autoheader autoconf; do
#      msg "$1,$prog"
      case $1,$prog in
        --force*,*|-f,*|--version,*|\
        --verbose,aclocal|--dry-run,aclocal|--install,aclocal|--output=*,aclocal|--warnings=*,aclocal|\
        --verbose,autoconf|--debug,autoconf|--output=*,autoconf|--warnings=*,autoconf|\
        --copy,libtoolize|--debug,libtoolize|--dry-run,libtoolize|--ltdl*,libtoolize|\
        --copy,automake|--add-missing,automake|--foreign,automake|--gnu,automake|--cygnus,automake)

          pushv "$prog" "$1"
          ;;

        -I,aclocal|\
        --output,autoconf|--output,aclocal|\
        --warnings,autoconf|--warnings,aclocal)

          pushv "$prog" "$1" "$2"
          
          n=2
#          shift
#          continue
          ;;

        --output,*|--warnings,*|-I,*)
        
          n=2
#          shift 2
#          continue
          ;;
      
        .,* | --copy,* | --debug,* | --add-missing,* | --foreign,*)

          true 
          ;;
      
        *,*)
        
          msg "No such argument ($1) for program $prog"
          return 1
          ;;
      esac
    done
    shift $n
  done
  
  dir="$1"

   #var_dump aclocal 1>&2

#  for dir
#  do (
#    if test -n "$auxdir" && test "${dir%/}" = "$auxdir"
#    then
#      msg "Skipping subdir: $dir"
#      continue
#    fi

    if cd "$dir" && test "$dir" != .
    then
      msg "cd `pwd`"
    fi

#    subdirs=`autotools_subdirs . | sed -e '/^\.$/d'`

    # Check for presence of an automake setup.
    if test -e Makefile.am || (
        sed -e 's/dnl.*$//g' configure.{ac,in} 2>/dev/null | 
        grep -q 'AM_INIT_AUTOMAKE'
      )
    then
      if test ! -e INSTALL -o ! -e AUTHORS -o ! -e COPYING
      then
        pushv automake --foreign
      fi
      
      # Scan for macros which contain checks requiring external, scripts/tools which 
      # can be handled by the GNU missing script.
      # Then at least one script must be effectively missing....
      if grep -qE '(A[CM]_CANONICAL|AM_MAINTAINER_MODE|AM_OUTPUT_DEPENDENCY_COMMANDS|AM_MISSING_PROG|YACC|LEX)' \
             configure.{ac,in} aclocal.m4 2>/dev/null && 
         cmd_some 'test ! -e "$^"' depcomp missing config.{sub,guess}
      then
        pushv automake --add-missing
      fi
    else
      unset automake
    fi

    # Check for presence of an autoheader setup.
    if (set -- *.h.in && test -e "$1") ||
       (sed -e 's/dnl.*$//g' configure.{ac,in} 2>/dev/null |
        grep -q 'A[CM]_CONFIG_HEADER')
    then
      :
    else
      unset autoheader
    fi

    # Check for presence of a libtool setup.
    if (sed -e 's/dnl.*$//g' configure.{ac,in} 2>/dev/null |
        grep -q 'A[CM]_PROG_LIBTOOL')
    then
      if test -n "$automake"
      then
        pushv libtoolize --automake
      fi
    else
      unset libtoolize
    fi

    # Determine AC_CONFIG_AUX_DIR
    if test -z "$auxdir"; then
      auxdir=`autotools_m4_macro 'AC_CONFIG_AUX_DIR' configure.ac`
    fi

    # Determine AC_CONFIG_MACRO_DIR
    if test -z "$macrodir"; then
      macrodir=`autotools_m4_macro 'AC_CONFIG_MACRO_DIR' configure.ac`
    fi

    # Find m4 libraries
     set -- $macrodir $auxdir

    acmasks=
    acdirs=$(for subdir in $*
    do
      if test ! -d $subdir; then
        continue
      fi

      if autotools_is_m4 $subdir/*; then
        verbose "Found M4 includes in subdirectory ${subdir%/}" 2

        echo "${subdir%/}"
      fi
    done)
  
    for acdir in $acdirs
    do
      case $acdir in
        *autom4te.cache*) continue ;;
      esac
    
      pushv aclocal -I $acdir
      pushv acmasks "$acdir/*"
    done

    pushv acmasks \
      ${aclocal+`aclocal --print-ac-dir`/*} \
      ${autoconf+$prefix/share/autoconf*/autoconf/*} \
      ${libtoolize+$prefix/share/libtool*/libltdl*/*}

    unset acfiles

    for acmask in $acmasks
    do
      if test -f "$acmask"
      then
        case "$acmask" in
          */aclocal.m4|aclocal.m4)
            ;;
          *)
            pushv acfiles "$acmask"
            ;;
        esac
      fi
    done
    
    acfunctions=`autotools_m4_defuns $acfiles | sort -u`
    
    if [ -f aclocal.m4 ]; then
      for required in `autotools_m4_defuns aclocal.m4 | sort -u`; do
        if ! isin $required $acfunctions; then
          warn "Unable to find function $required required by aclocal.m4, not running aclocal"
          #unset aclocal
          #break
        fi
      done
    fi    

    # Now run all the predefined commands...

#    IFS=" $IFS"

    cmds=

    for cmd in \
      "$libtoolize" \
      "$aclocal" \
      "$autoheader" \
      "$automake" \
      ${automake+"$aclocal"} \
      "$autoconf"
    do
      test -z "$cmd" && continue

      
            
     (exec 10>&1

      if ! ret=$( (msg "$cmd" 1>&10 && eval "$cmd $redir" 1>&2) && echo $? ) || 
            ! test $ret = 0
      then
        msg "Command failed ($ret):" $cmd
        exit $ret
      fi) || break
      IFS=$'\n' pushv cmds "$cmd"
    done
    
   if test $? = 0 && test "$save" = yes; then
     verbose "Saving autogen.sh in `pwd`" 1

     cat >autogen.sh <<EOF
#!/bin/sh
#
# `date --iso | sed s/-//g`

$cmds
EOF
     chmod +x autogen.sh
   fi

 #  ) || return $?

#   cd $topdir

#  done
  )
}

# autotools_build [source-directories...]
# -------------------------------------------------------------------------
autotools_build()
{
 (for DIR; do
    _autotools_build "$DIR" || exit $?
  done)
}

_autotools_build()
{
 (cd "$1"

  if [ -s Makefile ]; then
    exec make
  fi

 )
}

# -------------------------------------------------------------------------
autotools_subdirs()
{
  local dir subdir file IFS='
'
  test "$*" || set -- `autotools_scan`
  for dir
  do
    local dirs=

    if autotools_check $dir
    then
      local IFS="$space$tabstop$newline"

      for subdir in \
         $(sed -n -e "/SUBDIRS/ s,^.*SUBDIRS\s*=\?,, p" \
               ${autoconf_sources} ${automake_sources} 2>/dev/null)
      do
        subdir="${dir:+$dir/}$subdir"
        subdir="${subdir#./}"

        test -z $subdir || test -d $subdir && array_push_unique dirs $subdir
      done      
    fi
  done

  array_print dirs
}

# autotools_clean [directories...]
#
# Cleans files generated by autotools files in the specified directories.
# -------------------------------------------------------------------------
autotools_clean()
{
  local dir file IFS="$newline"

  test "$*" || set -- `autotools_scan`

  for dir
  do
    autotools_check "$dir" &&
   (cd $dir

    subdirs=. IFS="$space$newline$tabstop"

    pushv subdirs `autotools_subdirs`

    for subdir in $subdirs
    do
     (cd $subdir

      IFS="$space$newline$tabstop"

      if test -f Makefile || ./config.status 2>/dev/null
      then
        make distclean 2>&/dev/null || true
      
        grep -q '^#.*Generated by.*configure' Makefile
        rm -f Makefile
      fi

      for file in $autotools_files $autotools_generated
      do
        out=$dir/$subdir/$file
        out=${out//'/./'/'/'}
        out=${out//'/./'/'/'}
        out=${out//'/./'/'/'}
        out=${out#./}

        test -e "$file" && msg "Checking for $file..."

        if test -f "$file"
        then 
          echo ${out#./}
          rm -f "$file"
        fi
        
        if test -d "$file"
        then
          case "$file" in
            .* | */.* | autom4te.cache*)
              echo ${out#./}
              rm -rf "$file"
              ;;
          esac
        fi
      done)
    done)
  done
}

# -------------------------------------------------------------------------
autotools_options()
{
  local chars='_0-9A-Za-z'

  ./configure --help | sed -e "s/\s\+--/\n&/g" |
      sed -n -e "/^\s*--[-$chars]\+\(=[_A-Z]\+\)\?/ {
    /^\s*--[-$chars]\+\(=[_A-Z]\+\)\?\s\+[A-Za-z0-9]/! N
    s/^\s*--//
    s/\s\+/ /g
    p
  }"
 
}

# autotools_scan [directories...]
#
# checks one or more directories for the presence of configure{,.in,.ac}
# -------------------------------------------------------------------------
autotools_check()
{
  local n dir names='' IFS=" $newline$tabstop"

  for dir
  do
   (cd $dir

    eval set -- ${autoconf_sources} ${autoconf_files}

    for src
    do
      if test -e "$src"
      then
        echo "$dir"
        continue 2
      fi
    done

    errormsg "Not a valid autotools source tree:" $dir
    return 1)
  done
}

# autotools_builddir [source dirs...]
#
# for a list of autotools source trees it outputs a list of their out-of-source
# build directories...
# -------------------------------------------------------------------------
autotools_builddir()
{
  local dir parent base

  for dir
  do
    autotools_check "$dir" || return 1

    parent=`dirname "$dir"`
    base=`basename "$dir"`

    echo $parent/$base-build
  done
}

# autotools_commands [source dirs...]
#
# -------------------------------------------------------------------------
autotools_commands()
{
  local dir="$1" parent base cmds= IFS='
'
  shift

  autotools_check "$dir" >/dev/null || return 1

  for script in {autogen,bootstrap}{,.sh}
  do
    if test -e "$dir/$script"
    then
      if test -x "$dir/$script"
      then
        obj_set cmds "preconfigure" "./$script$IFS"
      else
        obj_set cmds "preconfigure" "sh $script$IFS"
      fi
    fi
  done

  echo "$cmds"
}

# autotools_buildfn <vars...>
# -------------------------------------------------------------------------
autotools_buildfn()
{
  local dir args name version srcdir IFS="
"
#  emit_startfn 'build'
#  set -- | grep '@prefix@/src' 1>&2

  name=`IFS="$obj_s" && obj_get "$*" name`
  version=`IFS="$obj_s" && obj_get "$*" version`
  srcdir=`IFS="$obj_s" && obj_get_default "$*" srcdir "${name:+$name-$version}"`

#  debug "SRCDIR: $srcdir"

  emit_cmd "cd ${srcdir//$version/\$version}"
  emit_cmd
  
  if preconfigure=`obj_get "$*" preconfigure` && test -n "$preconfigure"; then
   (for line in $preconfigure; do
      emit_cmd "$line"
    done)

    emit_cmd
  fi
  
  for var in build host prefix; do
    pushv args --$var='"$'$var'"'
  done
  
  emit_cmd_ml './configure' $args
  emit_cmd
  emit_cmd_ml 'make'
  emit_cmd_ml 'make DESTDIR="$PKG" install'

#  emit_endfn
}

# --- eof ---------------------------------------------------------------------
lib_buildsys_autotools_sh=:;}
